package com.aoip.telemetry.telemetry.core.config;

import com.aoip.telemetry.telemetry.core.exception.MsgCodecException;
import com.aoip.telemetry.telemetry.core.redis.RedisCache;
import com.aoip.telemetry.telemetry.entity.element.ElementAdditionFiledConfig;
import com.aoip.telemetry.telemetry.entity.element.ElementConfigEntity;
import com.aoip.telemetry.telemetry.entity.enums.CacheKeyEnum;
import com.aoip.telemetry.telemetry.entity.enums.MsgCodecStatusEnum;
import com.aoip.telemetry.telemetry.entity.equipment.StInfoConfigEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author chenbai
 * @version 1.0
 * @date 2021/8/9 17:38
 */
@Slf4j
@Component
public class ElementAnalysisConfig {

    @Resource
    private RedisCache redisCache;

    private StInfoConfigEntity loadNormalStList(String stCode, String funcCode) {
        StInfoConfigEntity stInfoConfigEntity = loadNormalStList(stCode);
        if (stInfoConfigEntity == null) {
            throw new MsgCodecException(MsgCodecStatusEnum.ST_NON_REGISTERED, "测站编码为：" + stCode);
        }
        return stInfoConfigEntity;
    }
    /**
     * 根据测站编码，功能码获取测站解析信息组
     * 逻辑关系：
     * 一个测站可以有多个解析组（一对多）；但是 同一测站且同一功能码 只有一条解析组数据（一对一）
     * 一个解析组 对应多个解析元素顺序信息（一对多）
     *
     * @param stCode   测站编码
     * @param funcCode 报文功能码编码，水资源协议中，再附加控制域C联合确定唯一性。格式为：功能码,控制域C
     * @return java.util.List<com.aoip.telemetry.telemetry.entity.common.ElementAnalysisGroupConfigEntity>
     * @author chenbai
     * @date 2021/8/10
     **/
    private List<String> getStAnalysisGroup(String stCode, String funcCode) {
        // 根据测站编码查询该测站所有解析组
        List<String> groupList = redisCache.getCacheList(CacheKeyEnum.REL_ST_ANALYSIS_GROUP + ":" + stCode);
        if (groupList.size() <= 0) {
            return loadDefaultAnalysisElementList();
        }
//        if (groupList.size() <= 0) {
//            throw new MsgCodecException(MsgCodecStatusEnum.ST_NON_ANALYSIS_GROUP, "根据测站未找到匹配的解析组，测站编码为：" + stCode);
//        }
        // 同一个测站编码和同一功能码按理只有一条关系数据，若存在多个解析组数据，则通过功能码进行区分
        List<List<String>> list = new ArrayList<>();
        for (String group : groupList) {
            if (!StringUtils.hasText(funcCode)) {
                funcCode = "";
            }
            List<String> tempList = redisCache.getCacheList(CacheKeyEnum.ANALYSIS_GROUP + ":" + group + funcCode);
            if (tempList != null && tempList.size() > 0) {
                list.add(tempList);
            }
        }
        if (list.size() == 1) {
            return list.get(0);
        } else {
            return loadDefaultAnalysisElementList();
        }
//        if (list.size() <= 0) {
//            throw new MsgCodecException(MsgCodecStatusEnum.ST_NON_ANALYSIS_GROUP, "根据测站未找到匹配的解析组，测站编码为：" + stCode);
//        }
//        if (list.size() > 1) {
//            throw new MsgCodecException(MsgCodecStatusEnum.ST_MORE_THAN_ONE_ANALYSIS_GROUP, "根据测站与功能码关联出不止一个解析组，测站编码为：" + stCode);
//        }
//        return list.get(0);
    }

    private List<String> loadDefaultAnalysisElementList(){
        List<String> result = new ArrayList<>();
        Collection<String> keys = redisCache.keys(CacheKeyEnum.ELEMENT + ":*");
        for (String key : keys) {
            ElementConfigEntity elementConfig = redisCache.getCacheObject(key);
            Integer analysisGroupSpecial = elementConfig.getAnalysisGroupSpecial();
            //测站没有关联解析组时，非解析组专用的解析要素不参与默认解析规则解析。
            if (analysisGroupSpecial != null && analysisGroupSpecial == 1) {
                continue;
            }
            result.add(key.substring(CacheKeyEnum.ELEMENT.getCode().length() + 1));
        }
        return result;
    }

    public List<ElementConfigEntity> getStAnalysis(String stcd, String funcCode) {
        List<String> analysisIdList = getStAnalysisGroup(stcd, funcCode);
        List<ElementConfigEntity> list = new ArrayList<>();
        analysisIdList.forEach(item -> {
            ElementConfigEntity elementConfigEntity = redisCache.getCacheObject(CacheKeyEnum.ELEMENT + ":" + item);
            list.add(elementConfigEntity);
        });
        return list;
    }

    /**
     * 加载表额外字段配置信息
     *
     * @return java.util.List<com.aoip.telemetry.telemetry.entity.common.ElementAdditionFiledConfig>
     * @author chenbai
     * @date 2021/11/16
     **/
    public List<ElementAdditionFiledConfig> getFieldExtConfigList() {
        Collection<String> keys = redisCache.keys(CacheKeyEnum.ELEMENT_ADDITION_FILED + ":*");
        List<ElementAdditionFiledConfig> list = new ArrayList<>();
        keys.forEach(item -> list.add(redisCache.getCacheObject(item)));
        return list;
    }

    /**
     * 加载未锁定且有效的测站编码。
     *
     * @return java.util.Set<java.lang.String>
     * @author chenbai
     * @date 2021/10/6
     **/
    private StInfoConfigEntity loadNormalStList(String stCode) {
        return redisCache.getCacheObject(CacheKeyEnum.STATION + ":" + stCode);
    }

}
